package com.zhuhjay.handler;

import com.zhuhjay.enums.HttpCode;
import com.zhuhjay.exception.ApiLimiterException;
import com.zhuhjay.exception.BasicBusinessException;
import com.zhuhjay.exception.ServerErrorException;
import com.zhuhjay.utils.result.Result;
import com.zhuhjay.utils.result.ResultBean;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.ObjectError;
import org.springframework.web.HttpMediaTypeNotSupportedException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.util.List;
import java.util.Set;

/**
 * 全局异常处理，需要注意每个异常的优先级，优先级高的异常需要放在前面
 * @author ZhuHJay
 * @date 2023/1/11 13:41
 */
@Slf4j
@RestControllerAdvice(basePackages = "com.zhuhjay.controller")
public class GlobalExceptionHandler {

    /** 用于捕获@RequestBody类型参数触发校验规则抛出的异常 **/
    @ExceptionHandler(value = MethodArgumentNotValidException.class)
    public Result handle(MethodArgumentNotValidException e) {
        StringBuilder sb = new StringBuilder();
        List<ObjectError> allErrors = e.getBindingResult().getAllErrors();
        for (ObjectError error : allErrors) {
            sb.append(error.getDefaultMessage()).append(";");
        }
        return ResultBean.fail(sb.toString());
    }

    /** 用于捕获@RequestParam/@PathVariable参数触发校验规则抛出的异常 **/
    @ExceptionHandler(value = ConstraintViolationException.class)
    public Result handle(ConstraintViolationException e) {
        StringBuilder sb = new StringBuilder();
        Set<ConstraintViolation<?>> conSet = e.getConstraintViolations();
        for (ConstraintViolation<?> con : conSet) {
            String message = con.getMessage();
            sb.append(message).append(";");
        }
        return ResultBean.fail(sb.toString());
    }

    /** 请求媒体类型不受支持 **/
    @ExceptionHandler(HttpMediaTypeNotSupportedException.class)
    public Result handle(HttpMediaTypeNotSupportedException e) {
        return ResultBean.fail("请求媒体类型不支持");
    }

    /** 请求方式不支持 **/
    @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
    public Result handle(HttpRequestMethodNotSupportedException e) {
        return ResultBean.fail(e.getMessage());
    }

    @ExceptionHandler(ServerErrorException.class)
    public Result handle(ServerErrorException e) {
        log.error("服务器异常", e);
        return ResultBean.fail(HttpCode.SERVER_ERROR);
    }

    /** 自定义异常，统一收集 **/
    @ExceptionHandler({BasicBusinessException.class, ApiLimiterException.class})
    public Result handle(RuntimeException e) {
        return ResultBean.fail(e.getMessage());
    }

    @ExceptionHandler(Exception.class)
    public Result handle(Exception e) {
        log.error("服务器异常", e);
        return ResultBean.fail(HttpCode.SERVER_ERROR);
    }

}
